package dm.ast.model.gen.factory;

import dm.sql.comp.ASTComplex;
import test.utility.Randomly;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author scy
 * @date 2024/4/16
 */
public class FromModelFactory extends BaseModelFactory{
    //根据宽度、深度返回from模型
    //主要以深度为主
    public static ComplexityModel fromModels(int wid_t, int dep_t){
        List<ComplexityModel> models = new ArrayList<ComplexityModel>();
        int t_widt = wid_t;
        int t_dept = dep_t;

        if(t_widt < t_dept){
            t_widt = t_dept;
        }
        models.addAll(modelDept(t_widt , t_dept));
        return Randomly.fromList(models);
    }

    //主要依据深度分配
    public static List<ComplexityModel> modelDept(int wid_t , int dep_t){
        List<ComplexityModel> models = new ArrayList<ComplexityModel>();
        ComplexityModel model;

        int min_wid = FactoryConstant.MIN_WIDT_COMP + dep_t - 1;
        if(wid_t < min_wid){  //当宽度不足以使用子查询时，仅能使用表连接，那么忽略总宽度要求
            model = new ComplexityModel(dep_t);
            for (int i = 0; i < model.count; i++) {
                model.comps[i].wid_t = 1;
                model.comps[i].dep_t = 1;

            }
            models.add(model);
        }else { //当宽度足够时可以使用子查询
            //仅1个子查询
            model = new ComplexityModel(1);
            model.comps[0].wid_t = wid_t - 1;
            model.comps[0].dep_t = dep_t;
            model.weight = FactoryConstant.WEIGHT_EXTREME;
            models.add(model);

            //混合分配
            models.addAll(modelChaos(wid_t , dep_t));
        }
        return models;
    }

    public static List<ComplexityModel> modelChaos(int wid_t , int dep_t){
        List<ComplexityModel> chaos = new ArrayList<ComplexityModel>();

        for (int i = 0; i < FactoryConstant.COUNT_AVERAGE; i++) {
            chaos.add(modelChaosLow(wid_t , dep_t));
        }

        return chaos;
    }


    //混合分配
    private static ComplexityModel modelChaosLow(int wid_t , int dep_t){
        ComplexityModel model;

        //多表连接 + 子查询
        int cnt = r.getInteger(2 , dep_t);
        ASTComplex[] comps = new ASTComplex[cnt];
        int i = 0;
        int tmp_dep_used = 0;
        int tmp_wid_used = 0;
        int tmp_dep = 0;
        for (i = 0; i < cnt; i++) {
            comps[i] = new ASTComplex();
            tmp_dep = r.getInteger(1 , dep_t -tmp_dep_used);
            if(tmp_dep == 1){  //关联表
                comps[i].wid_t = 1;
                comps[i].dep_t = 1;
            }else { //子查询
                comps[i].dep_t = tmp_dep;
                comps[i].wid_t = setWidtByDept(tmp_dep);
            }
            tmp_wid_used += comps[i].wid_t;
            tmp_dep_used += comps[i].dep_t;
            if(tmp_dep_used >= dep_t){
                break;
            }
        }
        if(i == cnt){
            i = cnt - 1;
        }
        model = new ComplexityModel(i + 1);
        tmp_dep_used = 0;
        for (i = 0; i < model.count; i++) {
            model.comps[i].wid_t = comps[i].wid_t;
            model.comps[i].dep_t = comps[i].dep_t;
            tmp_dep_used += comps[i].dep_t;
        }
        //还未验证总体深度是否满足要求
        if(tmp_dep_used < dep_t){
            i = r.getInteger(0 , model.count);
            model.comps[i].dep_t += dep_t - tmp_dep_used;
            model.comps[i].wid_t = setWidtByDept(model.comps[i].dep_t);
        }
        model.weight = FactoryConstant.WEIGHT_AVERAGE;
        for ( i = 0; i < model.count; i++) {
            if(model.comps[i].wid_t == 1 && model.comps[i].dep_t > 1){
                throw new IllegalArgumentException();
            }
        }
        return model;
    }
}
